//**************************************************
// Description: generate UDP frame
//**************************************************

//**************************************************
// include files
//**************************************************
`include "protocol_define.v"


module tx_frame_generator #(
    parameter IN_DATA_WIDTH     = 128   ,
    parameter IN_MOD_WIDTH      = 4     ,
    parameter OUT_ORDER_WIDTH   = 30    ,
    parameter OUT_ADDR_WIDTH    = 32    ,
    parameter OUT_DATA_WIDTH    = 32  
    ) (
    input                               clk ,
    input                               rst_n ,
    input   [9:0]                       ram_2p_cfg_register,
    // pre-module(response module)
    output                              protocol_gen_rdy ,
    output                              protocol_start_trans ,
    input       [IN_DATA_WIDTH-1-32:0]  protocol_gen_data ,
    input                               protocol_gen_sav ,
    input                               protocol_gen_val ,
    input                               protocol_gen_sop ,
    input                               protocol_gen_eop ,
    input                               convert_frame_info ,
    // frame info FIFO output
    input       [47:0]                  rd_DATALINK_dst_mac_fifo ,
    input       [47:0]                  rd_DATALINK_src_mac_fifo ,
    input       [31:0]                  rd_NETWORK_src_IP_fifo ,
    input       [31:0]                  rd_NETWORK_dst_IP_fifo ,
    input       [15:0]                  rd_TRANSPORT_src_port_fifo ,
    input       [15:0]                  rd_TRANSPORT_dst_port_fifo ,
    // frame arbiter
    input                               UDP_frame_rdy ,
    output      [IN_DATA_WIDTH-1:0]     UDP_frame_data ,
    output      [IN_MOD_WIDTH-1:0]      UDP_frame_mod ,
    output                              UDP_frame_sav ,
    output                              UDP_frame_val ,
    output                              UDP_frame_sop ,
    output                              UDP_frame_eop
) ;

//**************************************************
// generate the protocol content
//**************************************************
    //----------------------------------------------
    // signal declare
    //----------------------------------------------
    // FIFO write
    wire                                            frame_info_FIFO_wren ;
    wire    [1+1+IN_MOD_WIDTH+IN_DATA_WIDTH-1:0]    frame_info_FIFO_wdata ;
    // UDP generator
    wire                                            UDP_generator_rdy ;
    wire    [47:0]                                  UDP_generator_dst_mac ;
    wire    [47:0]                                  UDP_generator_src_mac ;
    wire    [31:0]                                  UDP_generator_src_ip ;
    wire    [31:0]                                  UDP_generator_dst_ip ;
    wire    [15:0]                                  UDP_generator_src_port ;
    wire    [15:0]                                  UDP_generator_dst_port ;
    wire    [10:0]                                  UDP_generator_length_in ;
    wire    [15:0]                                  UDP_generator_checksum_in ;
    wire                                            UDP_generator_gen_finish_in ;

    //----------------------------------------------
    // instance
    //----------------------------------------------
    tx_protocol_generator #(
        .IN_DATA_WIDTH                  (IN_DATA_WIDTH              ) ,
        .IN_MOD_WIDTH                   (IN_MOD_WIDTH               ) ,
        .OUT_ORDER_WIDTH                (OUT_ORDER_WIDTH            ) ,
        .OUT_ADDR_WIDTH                 (OUT_ADDR_WIDTH             ) ,
        .OUT_DATA_WIDTH                 (OUT_DATA_WIDTH             ) ,
        .ACTION_ADDITION_SEQ            (`PROTOCOL_ACTION_ADDITION  )
        )
    inst_tx_protocol_generator (
        .clk                            (clk                        ) ,
        .rst_n                          (rst_n                      ) ,
        // response module interface
        .protocol_gen_rdy               (protocol_gen_rdy           ) ,
        .protocol_start_trans           (protocol_start_trans       ) ,
        .protocol_gen_data              (protocol_gen_data          ) ,
        .protocol_gen_sav               (protocol_gen_sav           ) ,
        .protocol_gen_val               (protocol_gen_val           ) ,
        .protocol_gen_sop               (protocol_gen_sop           ) ,
        .protocol_gen_eop               (protocol_gen_eop           ) ,
        .convert_frame_info             (convert_frame_info         ) ,
        // frame info FIFO interface
        .rd_DATALINK_dst_mac_fifo       (rd_DATALINK_dst_mac_fifo   ) ,
        .rd_DATALINK_src_mac_fifo       (rd_DATALINK_src_mac_fifo   ) ,
        .rd_NETWORK_src_IP_fifo         (rd_NETWORK_src_IP_fifo     ) ,
        .rd_NETWORK_dst_IP_fifo         (rd_NETWORK_dst_IP_fifo     ) ,
        .rd_TRANSPORT_src_port_fifo     (rd_TRANSPORT_src_port_fifo ) ,
        .rd_TRANSPORT_dst_port_fifo     (rd_TRANSPORT_dst_port_fifo ) ,
        // FIFO write enable
        .protocol_FIFO_wr_en            (frame_info_FIFO_wren       ) ,
        .protocol_FIFO_wr_data          (frame_info_FIFO_wdata      ) ,
        // UDP header generator
        .UDP_generator_rdy              (UDP_generator_rdy          ) ,
        .DATALINK_dst_mac_fifo_o        (UDP_generator_dst_mac      ) ,
        .DATALINK_src_mac_fifo_o        (UDP_generator_src_mac      ) ,
        .NETWORK_src_IP_fifo_o          (UDP_generator_src_ip       ) ,
        .NETWORK_dst_IP_fifo_o          (UDP_generator_dst_ip       ) ,
        .TRANSPORT_src_port_fifo_o      (UDP_generator_src_port     ) ,
        .TRANSPORT_dst_port_fifo_o      (UDP_generator_dst_port     ) ,
        .protocol_length                (UDP_generator_length_in    ) ,
        .protocol_CRC_checksum          (UDP_generator_checksum_in  ) ,
        .protocol_gen_finish            (UDP_generator_gen_finish_in    )
    );



//**************************************************
// generate protocol FIFO
//**************************************************
    //----------------------------------------------
    // FIFO read signal and state signal
    //----------------------------------------------
    wire                                            frame_info_FIFO_rden ;
    wire    [1+1+IN_MOD_WIDTH+IN_DATA_WIDTH-1:0]    frame_info_FIFO_rdata ;
    wire                                            frame_info_FIFO_full ;
    wire                                            frame_info_FIFO_empty ;

`ifdef FPGA_MODE
    protocol_gen_FIFO_256d_134w inst_protocol_gen_FIFO_256d_134w (
        .clk                (clk                    ),  // input wire clk
        .rst                ( (!rst_n)              ),  // input wire rst
        .din                (frame_info_FIFO_wdata  ),  // input wire [133 : 0] din
        .wr_en              (frame_info_FIFO_wren   ),  // input wire wr_en
        .rd_en              (frame_info_FIFO_rden   ),  // input wire rd_en
        .dout               (frame_info_FIFO_rdata  ),  // output wire [133 : 0] dout
        .full               (frame_info_FIFO_full   ),  // output wire full
        .empty              (frame_info_FIFO_empty  )   // output wire empty
    ) ;
`else
    fifo_256d_134w_wrapper inst_protocol_gen_FIFO_256d_134w (
        .clk                (clk                    ),  // input wire clk
        .rst                ( (!rst_n)              ),  // input wire rst
        .ram_2p_cfg_register(ram_2p_cfg_register    ),
        .din                (frame_info_FIFO_wdata  ),  // input wire [133 : 0] din
        .wr_en              (frame_info_FIFO_wren   ),  // input wire wr_en
        .rd_en              (frame_info_FIFO_rden   ),  // input wire rd_en
        .dout               (frame_info_FIFO_rdata  ),  // output wire [133 : 0] dout
        .full               (frame_info_FIFO_full   ),  // output wire full
        .empty              (frame_info_FIFO_empty  )   // output wire empty
    ) ;
`endif

//**************************************************
// UDP generator
//**************************************************
    //----------------------------------------------
    // UDP generator signal declare
    //----------------------------------------------
    wire                                            IP_generator_rdy ;
    wire    [IN_DATA_WIDTH-1:0]                     IP_generator_data ;
    wire    [IN_MOD_WIDTH-1:0]                      IP_generator_mod ;
    wire                                            IP_generator_sav ;
    wire                                            IP_generator_val ;
    wire                                            IP_generator_sop ;
    wire                                            IP_generator_eop ;
    wire    [10:0]                                  IP_generator_length_in ;
    wire    [15:0]                                  IP_generator_checksum_in ;
    wire    [47:0]                                  IP_generator_dst_mac ;
    wire    [47:0]                                  IP_generator_src_mac ;
    wire    [31:0]                                  IP_generator_src_IP ;
    wire    [31:0]                                  IP_generator_dst_IP ;

    tx_UDP_generator #(
        .IN_DATA_WIDTH                  (IN_DATA_WIDTH              ) ,
        .IN_MOD_WIDTH                   (IN_MOD_WIDTH               )
        )
    inst_tx_UDP_generator (
        .clk                            (clk                        ) ,
        .rst_n                          (rst_n                      ) ,
        // protocol gen FIFO read
        .frame_info_FIFO_rden           (frame_info_FIFO_rden       ) ,
        .frame_info_FIFO_rdata          (frame_info_FIFO_rdata      ) ,
        // protocol generator
        .UDP_generator_rdy              (UDP_generator_rdy          ) ,
        .DATALINK_dst_mac_fifo_i        (UDP_generator_dst_mac      ) ,
        .DATALINK_src_mac_fifo_i        (UDP_generator_src_mac      ) ,
        .NETWORK_src_IP_fifo_i          (UDP_generator_src_ip       ) ,
        .NETWORK_dst_IP_fifo_i          (UDP_generator_dst_ip       ) ,
        .TRANSPORT_src_port_fifo_i      (UDP_generator_src_port     ) ,
        .TRANSPORT_dst_port_fifo_i      (UDP_generator_dst_port     ) ,
        .protocol_length                (UDP_generator_length_in    ) ,
        .protocol_CRC_checksum          (UDP_generator_checksum_in  ) ,
        .protocol_gen_finish            (UDP_generator_gen_finish_in) ,
        // IP generator
        .IP_gen_rdy                     (IP_generator_rdy           ) ,
        .protocol_gen_data              (IP_generator_data          ) ,
        .protocol_gen_mod               (IP_generator_mod           ) ,
        .protocol_gen_sav               (IP_generator_sav           ) ,
        .protocol_gen_val               (IP_generator_val           ) ,
        .protocol_gen_sop               (IP_generator_sop           ) ,
        .protocol_gen_eop               (IP_generator_eop           ) ,
        .protocol_gen_length            (IP_generator_length_in     ) ,
        .protocol_gen_checksum          (IP_generator_checksum_in   ) ,
        .DATALINK_dst_mac_fifo_o        (IP_generator_dst_mac       ) ,
        .DATALINK_src_mac_fifo_o        (IP_generator_src_mac       ) ,
        .NETWORK_src_IP_fifo_o          (IP_generator_src_IP        ) ,
        .NETWORK_dst_IP_fifo_o          (IP_generator_dst_IP        )
    ) ;



//**************************************************
// IP frame generator
//**************************************************
    tx_IP_generator #(
        .IN_DATA_WIDTH                  (IN_DATA_WIDTH              ) ,
        .IN_MOD_WIDTH                   (IN_MOD_WIDTH               ) ,
        .IP_VERSION                     (`IP_VERSION                ) , // 4b
        .IP_HEADER_LENGTH               (`IP_HEADER_LENGTH          ) , // 4b
        .IP_TOS                         (`IP_TOS                    ) , // 8b
        // IP_TOTAL_LENGTH                                              // 16b
        .IP_IDENTIFICATION              (`IP_IDENTIFICATION         ) , // 16b
        .IP_FLAG                        (`IP_FLAG                   ) , // 3b
        .IP_OFFSET                      (`IP_OFFSET                 ) , // 13b
        .IP_TTL                         (`IP_TTL                    ) , // 8b
        .IP_PROTOCOL                    (`IP_PROTOCOL               )   // 8b
        )
    inst_tx_IP_generator (
        .clk                            (clk                        ) ,
        .rst_n                          (rst_n                      ) ,
        // UDP generator
        .IP_gen_rdy                     (IP_generator_rdy           ) ,
        .IP_generator_data              (IP_generator_data          ) ,
        .IP_generator_mod               (IP_generator_mod           ) ,
        .IP_generator_sav               (IP_generator_sav           ) ,
        .IP_generator_val               (IP_generator_val           ) ,
        .IP_generator_sop               (IP_generator_sop           ) ,
        .IP_generator_eop               (IP_generator_eop           ) ,
        .IP_generator_length_in         (IP_generator_length_in     ) ,
        .IP_generator_checksum_in       (IP_generator_checksum_in   ) ,
        .IP_generator_dst_mac           (IP_generator_dst_mac       ) ,
        .IP_generator_src_mac           (IP_generator_src_mac       ) ,
        .IP_generator_src_IP            (IP_generator_src_IP        ) ,
        .IP_generator_dst_IP            (IP_generator_dst_IP        ) ,
        // tx channel arbiter
        .UDP_frame_rdy                  (UDP_frame_rdy              ) ,
        .UDP_frame_data                 (UDP_frame_data             ) ,
        .UDP_frame_mod                  (UDP_frame_mod              ) ,
        .UDP_frame_sav                  (UDP_frame_sav              ) ,
        .UDP_frame_val                  (UDP_frame_val              ) ,
        .UDP_frame_sop                  (UDP_frame_sop              ) ,
        .UDP_frame_eop                  (UDP_frame_eop              )
    ) ;
endmodule
